{*******************************************************************************
* The contents of this file are used with permission, subject to the Mozilla   *
* Public License Version 1.1 (the "License"); you may not use this file except *
* in compliance with the License. You may obtain a copy of the License at      *
* http://www.mozilla.org/MPL/                                                  *
*                                                                              *
* Software distributed under the License is distributed on an "AS IS" basis,   *
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for *
* the specific language governing rights and limitations under the License.    *
*                                                                              *
* The Original Code is distributed as part of the "mediate" product and is     *
* Copyright (C) @home media limited. All Rights Reserved.                      *
*                                                                              *
* Email: support@athomemedia.co.uk                                             *
* Web:   http://www.athomemedia.co.uk                                          *
*******************************************************************************}

unit ConfigurationForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ExtCtrls, VellemanManager, VellemanInputs;

type
  TfrmVellemanConfig = class(TForm)
    btClose: TButton;
    tcTabControl: TTabControl;
    nbSettings: TNotebook;
    pnAnalog: TPanel;
    pnGeneral: TPanel;
    pnDigital: TPanel;
    gbCardSettings: TGroupBox;
    Label6: TLabel;
    Label3: TLabel;
    ecCardAddress: TComboBox;
    edPollInterval: TEdit;
    udPollInterval: TUpDown;
    gbAnalog1Settings: TGroupBox;
    Label1: TLabel;
    cbAutoAnalog1: TCheckBox;
    edAnalogOut1: TEdit;
    udAnalogOut1: TUpDown;
    gbAnalog2Settings: TGroupBox;
    Label2: TLabel;
    cbAutoAnalog2: TCheckBox;
    edAnalogOut2: TEdit;
    udAnalogOut2: TUpDown;
    gbAnalogInputs: TGroupBox;
    btAddAnalog: TButton;
    lvAnalog: TListView;
    btEditAnalog: TButton;
    btDeleteAnalog: TButton;
    gbDigitalInputs: TGroupBox;
    lvDigital: TListView;
    btEditDigital: TButton;
    Label5: TLabel;
    edCounter1Delay: TEdit;
    udCounter1Delay: TUpDown;
    udCounter2Delay: TUpDown;
    edCounter2Delay: TEdit;
    Label4: TLabel;
    procedure FormShow(Sender: TObject);
    procedure btCloseClick(Sender: TObject);
    procedure tcTabControlChange(Sender: TObject);
    procedure cbAutoAnalogClick(Sender: TObject);
    procedure lvAnalogChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure lvDigitalChange(Sender: TObject; Item: TListItem;
      Change: TItemChange);
    procedure btAddAnalogClick(Sender: TObject);
    procedure btEditAnalogClick(Sender: TObject);
    procedure btDeleteAnalogClick(Sender: TObject);
    procedure btEditDigitalClick(Sender: TObject);
    procedure lvAnalogDblClick(Sender: TObject);
    procedure lvDigitalDblClick(Sender: TObject);
  private
    { Private declarations }
    FWorking: Boolean;
    FVelleman: TAHMVellemanManager;
    function GetCurrentAction: TAHMVellemanInputAction;
    function GetCurrentActions: TAHMVellemanInputActions;
    function GetCurrentActionsType: TAHMVellemanInputType;
    procedure PopulateAnalogInputs;
    procedure PopulateDigitalInputs;
    procedure PopulateInputs(lvInputs: TListView);
    procedure ShowVellemanSettings;
    procedure UpdateSettingsControls;
    procedure UpdateAnalogControls;
    procedure UpdateDigitalControls;
    procedure UpdateVellemanSettings;
  protected
    { Protected declarations }
    property CurrentAction: TAHMVellemanInputAction read GetCurrentAction;
    property CurrentActions: TAHMVellemanInputActions read GetCurrentActions;
    property CurrentActionsType: TAHMVellemanInputType read GetCurrentActionsType;
    property VellemanManager: TAHMVellemanManager read FVelleman write FVelleman;
  public
    { Public declarations }
    class function Configure(Velleman: TAHMVellemanManager): Boolean;
  end;


implementation

{$R *.dfm}

uses InputActionForm;

type
  TConfigTabs = (tbGeneral, tbAnalog1, tbAnalog2, tbDigital);
  TConfigPages = (pgGeneral, pgAnalog, pgDigital);

class function TfrmVellemanConfig.Configure(Velleman: TAHMVellemanManager): Boolean;
begin
  with Self.Create(nil) do
  try
    VellemanManager := Velleman;
    Result := (ShowModal = mrOK);
  finally
    Free;
  end;
end;

procedure TfrmVellemanConfig.FormShow(Sender: TObject);
begin
  // Display current configuration details
  ShowVellemanSettings;
end;

procedure TfrmVellemanConfig.tcTabControlChange(Sender: TObject);
begin
  // Select appropriate page - we reuse analog input page twice
  case TConfigTabs(tcTabControl.TabIndex) of
    tbGeneral: nbSettings.PageIndex := Ord(pgGeneral);
    tbAnalog1, tbAnalog2: nbSettings.PageIndex := Ord(pgAnalog);
    tbDigital: nbSettings.PageIndex := Ord(pgDigital);
  end;

  // Refresh appropriate settings page of notebook
  case TConfigPages(nbSettings.PageIndex) of
    pgAnalog: PopulateAnalogInputs;
    pgDigital: PopulateDigitalInputs;
  end;
end;

procedure TfrmVellemanConfig.cbAutoAnalogClick(Sender: TObject);
begin
  // Configure general settings controls
  UpdateSettingsControls;
end;

procedure TfrmVellemanConfig.lvAnalogChange(Sender: TObject; Item: TListItem; Change: TItemChange);
begin
  UpdateAnalogControls;
end;

procedure TfrmVellemanConfig.lvAnalogDblClick(Sender: TObject);
begin
  // Double click analog action to edit
  if Assigned(lvAnalog.Selected) then btEditAnalog.Click;
end;

procedure TfrmVellemanConfig.lvDigitalChange(Sender: TObject; Item: TListItem; Change: TItemChange);
begin
  UpdateDigitalControls;
end;

procedure TfrmVellemanConfig.lvDigitalDblClick(Sender: TObject);
begin
  // Double click digital action to edit
  if Assigned(lvDigital.Selected) then btEditDigital.Click;
end;

procedure TfrmVellemanConfig.btAddAnalogClick(Sender: TObject);
var
  NewAction: TAHMVellemanAnalogAction;
begin
  // Create temporary action instance for editing
  NewAction := TAHMVellemanAnalogAction.Create(nil);
  NewAction.InputType := CurrentActionsType;
  try
    if TfrmInputActionConfig.Configure(FVelleman, NewAction) then
    begin
      CurrentActions.Add.Assign(NewAction);
      PopulateAnalogInputs;
    end;
  finally
    NewAction.Free;
  end;
end;

procedure TfrmVellemanConfig.btEditAnalogClick(Sender: TObject);
begin
  if TfrmInputActionConfig.Configure(FVelleman, CurrentAction) then
    PopulateAnalogInputs;
end;

procedure TfrmVellemanConfig.btDeleteAnalogClick(Sender: TObject);
begin
  CurrentActions.Delete(CurrentAction.Index);
  PopulateAnalogInputs;
end;

procedure TfrmVellemanConfig.btEditDigitalClick(Sender: TObject);
begin
  if TfrmInputActionConfig.Configure(FVelleman, CurrentAction) then
    PopulateDigitalInputs;
end;

procedure TfrmVellemanConfig.btCloseClick(Sender: TObject);
begin
  // Update modified application settings
  UpdateVellemanSettings;
end;

function TfrmVellemanConfig.GetCurrentAction: TAHMVellemanInputAction;
begin
  // Set default result - no current action
  Result := nil;

  if (nbSettings.PageIndex = Ord(pgAnalog)) and Assigned(lvAnalog.Selected) then
    Result := TAHMVellemanInputAction(lvAnalog.Selected.Data)
  else if (nbSettings.PageIndex = Ord(pgDigital)) and Assigned(lvDigital.Selected) then
    Result := TAHMVellemanInputAction(lvDigital.Selected.Data);
end;

function TfrmVellemanConfig.GetCurrentActions: TAHMVellemanInputActions;
begin
  // Current actions depends on selected tab
  case CurrentActionsType of
    inAnalog1: Result := FVelleman.Inputs.AnalogInputs;
    inAnalog2: Result := FVelleman.Inputs.AnalogInputs;
    inDigital: Result := FVelleman.Inputs.DigitalInputs;
    else Result := nil;
  end;
end;

function TfrmVellemanConfig.GetCurrentActionsType: TAHMVellemanInputType;
begin
  // Current actions type depends on selected tab
  case TConfigTabs(tcTabControl.TabIndex) of
    tbAnalog1: Result := inAnalog1;
    tbAnalog2: Result := inAnalog2;
    tbDigital: Result := inDigital;
    else Result := inUnknown;
  end;
end;

procedure TfrmVellemanConfig.PopulateAnalogInputs;
begin
  PopulateInputs(lvAnalog);
  UpdateAnalogControls;
end;

procedure TfrmVellemanConfig.PopulateDigitalInputs;
begin
  PopulateInputs(lvDigital);
  UpdateDigitalControls;
end;

procedure TfrmVellemanConfig.PopulateInputs(lvInputs: TListView);
var
  i: Integer;
begin
  FWorking := True;
  try
    lvInputs.Items.BeginUpdate;
    lvInputs.Items.Clear;

    // Populate list of relevant actions
    for i := 0 to Pred(CurrentActions.Count) do
      if CurrentActions.Actions[i].InputType = CurrentActionsType then
        with lvInputs.Items.Add do
        begin
          Caption := CurrentActions.Actions[i].InputName;
          SubItems.Add(CurrentActions.Actions[i].ShortAction);
          SubItems.Add(CurrentActions.Actions[i].LongAction);
          Data := CurrentActions.Actions[i];
        end;
  finally
    lvInputs.Items.EndUpdate;
    FWorking := False;
  end;
end;

procedure TfrmVellemanConfig.ShowVellemanSettings;
begin
  // Update simple configuration items
  udPollInterval.Position := FVelleman.Inputs.PollingInterval;
  ecCardAddress.ItemIndex := FVelleman.DefaultAddress;
  udCounter1Delay.Position := FVelleman.DebounceChannel1;
  udCounter2Delay.Position := FVelleman.DebounceChannel2;

  udAnalogOut1.Position := FVelleman.DebounceChannel1;
  udAnalogOut2.Position := FVelleman.DebounceChannel2;
  cbAutoAnalog1.Checked := FVelleman.AutoAnalogOutput1;
  cbAutoAnalog2.Checked := FVelleman.AutoAnalogOutput2;
  udAnalogOut1.Position := FVelleman.AutoAnalogValue1;
  udAnalogOut2.Position := FVelleman.AutoAnalogValue2;

  // Show general settings page initially
  tcTabControl.TabIndex := Ord(tbGeneral);
  nbSettings.PageIndex := Ord(pgGeneral);

  // Ensure settings controls are in sync with this application
  UpdateSettingsControls;
end;

procedure TfrmVellemanConfig.UpdateSettingsControls;
begin
  edAnalogOut1.Enabled := cbAutoAnalog1.Checked;
  udAnalogOut1.Enabled := cbAutoAnalog1.Checked;
  edAnalogOut2.Enabled := cbAutoAnalog2.Checked;
  udAnalogOut2.Enabled := cbAutoAnalog2.Checked;
end;

procedure TfrmVellemanConfig.UpdateAnalogControls;
begin
  if not FWorking then
  begin
    btEditAnalog.Enabled := Assigned(CurrentAction);
    btDeleteAnalog.Enabled := Assigned(CurrentAction);
  end;
end;

procedure TfrmVellemanConfig.UpdateDigitalControls;
begin
  if not FWorking then
  begin
    btEditDigital.Enabled := Assigned(CurrentAction);
  end;
end;

procedure TfrmVellemanConfig.UpdateVellemanSettings;
begin
  FVelleman.Inputs.PollingInterval := udPollInterval.Position;
  FVelleman.DefaultAddress := ecCardAddress.ItemIndex;
  FVelleman.DebounceChannel1 := udCounter1Delay.Position;
  FVelleman.DebounceChannel2 := udCounter2Delay.Position;
  FVelleman.AutoAnalogOutput1 := cbAutoAnalog1.Checked;
  FVelleman.AutoAnalogOutput2 := cbAutoAnalog2.Checked;
  FVelleman.AutoAnalogValue1 := udAnalogOut1.Position;
  FVelleman.AutoAnalogValue2 := udAnalogOut2.Position;
end;



end.
